package com.ssy.lingxi.order.serviceimpl.feign;

import com.ssy.lingxi.common.constant.basic.FundModeEnum;
import com.ssy.lingxi.common.constant.order.OrderPayChannelEnum;
import com.ssy.lingxi.common.constant.order.OrderPayTypeEnum;
import com.ssy.lingxi.common.constant.settle.SettlementOrderTypeEnum;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.dto.model.constant.SettleAccountQueueMessageTypeEnum;
import com.ssy.lingxi.dto.model.constant.SettleAccountsConstant;
import com.ssy.lingxi.dto.request.*;
import com.ssy.lingxi.dto.response.InvoiceMessageResponse;
import com.ssy.lingxi.dto.response.MemberSettlementStrategyResponse;
import com.ssy.lingxi.feign.InvoiceMessageControllerFeigen;
import com.ssy.lingxi.feign.PlatformConfigControllerFeign;
import com.ssy.lingxi.order.entity.OrderDO;
import com.ssy.lingxi.order.model.dto.OrderInvoiceDTO;
import com.ssy.lingxi.order.model.dto.OrderSettlementDTO;
import com.ssy.lingxi.order.model.vo.basic.response.OrderPayChannelDetailVO;
import com.ssy.lingxi.order.model.vo.basic.response.OrderPayTypeDetailVO;
import com.ssy.lingxi.order.service.feign.ISettleAccountFeignService;
import com.ssy.lingxi.order.utils.NumberUtil;
import com.ssy.lingxi.order.utils.OrderDateTimeUtil;
import com.ssy.lingxi.order.utils.OrderStringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 资金账户服务Feign接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-09-14
 */
@Service
public class SettleAccountFeignServiceImpl implements ISettleAccountFeignService {
    private static final Logger logger = LoggerFactory.getLogger(SettleAccountFeignServiceImpl.class);

    @Resource
    private InvoiceMessageControllerFeigen invoiceMessageControllerFeign;

    @Resource
    private PlatformConfigControllerFeign platformConfigControllerFeign;

    @Resource
    private RabbitTemplate rabbitTemplate;


    /**
     * 查询供应商发票信息
     *
     * @param vendorMemberIds 供应商Id列表
     * @return 查询结果
     */
    @Override
    public Wrapper<List<OrderInvoiceDTO>> findMemberInvoices(List<Long> vendorMemberIds) {
        if(CollectionUtils.isEmpty(vendorMemberIds)) {
            return Wrapper.success(new ArrayList<>());
        }

        InvoiceMessageListRequest requests = new InvoiceMessageListRequest();
        requests.setMemberList(vendorMemberIds.stream().map(vendorMemberId -> {
            InvoiceMessageGetRequest request = new InvoiceMessageGetRequest();
            request.setMemberId(vendorMemberId);
            return request;
        }).collect(Collectors.toList()));

        Wrapper<List<InvoiceMessageResponse>> invoiceResult = invoiceMessageControllerFeign.getMemberInvoiceMessageList(requests);
        if(invoiceResult.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(invoiceResult.getCode(), invoiceResult.getMessage());
        }

        return Wrapper.success(CollectionUtils.isEmpty(invoiceResult.getData()) ? new ArrayList<>() : invoiceResult.getData().stream().map(r -> {
            OrderInvoiceDTO invoice = new OrderInvoiceDTO();
            invoice.setMemberId(r.getMemberId());
            invoice.setInvoiceId(r.getId());
            invoice.setInvoiceKind(r.getKind());
            invoice.setInvoiceType(r.getType());
            invoice.setTitle(StringUtils.hasLength(r.getInvoiceTitle()) ? r.getInvoiceTitle() : "");
            invoice.setTaxNo(StringUtils.hasLength(r.getTaxNo()) ? r.getTaxNo() : "");
            invoice.setBank(StringUtils.hasLength(r.getBankOfDeposit()) ? r.getBankOfDeposit() : "");
            invoice.setAccount(StringUtils.hasLength(r.getAccount()) ? r.getAccount() : "");
            invoice.setAddress(StringUtils.hasLength(r.getAddress()) ? r.getAddress() : "");
            invoice.setPhone(StringUtils.hasLength(r.getTel()) ? r.getTel() : "");
            invoice.setDefaultInvoice(!NumberUtil.isNullOrZero(r.getIsDefault()) && r.getIsDefault().compareTo(1) == 0);
            return invoice;
        }).collect(Collectors.toList()));
    }

    /**
     * 查询账期与月结支付方式
     *
     * @param order 订单
     * @return 账期与月结支付方式
     */
    @Override
    public Wrapper<OrderPayTypeDetailVO> findSettlementPaySetting(OrderDO order) {
        return findSettlementPaySetting(order.getBuyerMemberId(), order.getBuyerRoleId(), order.getVendorMemberId(), order.getVendorRoleId());
    }

    /**
     * 查询账期与月结支付方式是否开启
     *
     * @param buyerMemberId  采购会员Id
     * @param buyerRoleId    采购会员角色Id
     * @param vendorMemberId 供应会员Id
     * @param vendorRoleId   供应会员角色Id
     * @return 账期与月结支付方式
     */
    @Override
    public Wrapper<OrderPayTypeDetailVO> findSettlementPaySetting(Long buyerMemberId, Long buyerRoleId, Long vendorMemberId, Long vendorRoleId) {
        MemberSettlementStrategyRequest request = new MemberSettlementStrategyRequest();
        request.setSettlementOrderType(3);
        request.setMemberId(buyerMemberId);
        request.setRoleId(buyerRoleId);
        request.setSupplierMemberId(vendorMemberId);
        request.setSupplierRoleId(vendorRoleId);

        Wrapper<MemberSettlementStrategyResponse> result = platformConfigControllerFeign.getMemberSettlementStrategy(request);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        OrderPayTypeDetailVO detailVO = null;
        if(result.getData() != null) {
            detailVO = new OrderPayTypeDetailVO();
            //结算支付的资金归集模式必定为“会员直接到账”
            detailVO.setFundMode(FundModeEnum.DIRECT_TO_ACCOUNT.getCode());
            detailVO.setPayType(OrderPayTypeEnum.SETTLEMENT.getCode());
            detailVO.setPayTypeName(OrderPayTypeEnum.SETTLEMENT.getName());
            if(result.getData().getSettlementWay().equals(1)) {
                String days = LocaleContextHolder.getLocale().getLanguage().toLowerCase().equals("zh") ? "天" : "";
                detailVO.setPayChannels(Stream.of(new OrderPayChannelDetailVO(OrderPayChannelEnum.ACCOUNT_PERIOD.getCode(), OrderPayChannelEnum.ACCOUNT_PERIOD.getName().concat(String.valueOf(result.getData().getSettlementDays())).concat(days))).collect(Collectors.toList()));
            } else {
                String date = LocaleContextHolder.getLocale().getLanguage().toLowerCase().equals("zh") ? "号" : "";
                detailVO.setPayChannels(Stream.of(new OrderPayChannelDetailVO(OrderPayChannelEnum.MONTHLY_SETTLEMENT.getCode(), OrderPayChannelEnum.MONTHLY_SETTLEMENT.getName().concat(String.valueOf(result.getData().getSettlementDate())).concat(date))).collect(Collectors.toList()));
            }
        }

        return Wrapper.success(detailVO);
    }

    /**
     * 订单发货信息通知给结算服务
     *
     * @param settlementDTO 订单发货信息DTO
     */
    @Async
    @Override
    public void notifyOrderSettlement(OrderSettlementDTO settlementDTO) {
        SettlementOrderVO orderVO = new SettlementOrderVO();
        orderVO.setBillId(settlementDTO.getOrderId());
        orderVO.setBillNo(settlementDTO.getOrderNo());
        orderVO.setBillDate(settlementDTO.getCreateTime());
        orderVO.setBillAbstract(settlementDTO.getDigest());
        orderVO.setBillAmount(settlementDTO.getTotalAmount());
        orderVO.setBillType(1);
        orderVO.setBuyerMemberId(settlementDTO.getBuyerMemberId());
        orderVO.setBuyerRoleId(settlementDTO.getBuyerRoleId());
        orderVO.setVendorMemberId(settlementDTO.getVendorMemberId());
        orderVO.setVendorRoleId(settlementDTO.getVendorRoleId());
        orderVO.setSourceContractId(settlementDTO.getContractId());
        orderVO.setPayee(settlementDTO.getVendorMemberName());
        orderVO.setPayer(settlementDTO.getBuyerMemberName());
        orderVO.setDeliveryBatch(settlementDTO.getBatchNo());
        orderVO.setDeliveryNo(settlementDTO.getDeliveryNo());
        orderVO.setDeliveryTime(settlementDTO.getDeliveryTime());
        orderVO.setReceiveNo(settlementDTO.getReceiveNo());
        orderVO.setReceiveTime(settlementDTO.getReceiveTime());
        orderVO.setOrderStatus(settlementDTO.getOuterStatusName());
        orderVO.setOrderType(settlementDTO.getOrderType());

        orderVO.setProducts(settlementDTO.getReceivedProducts().stream().map(p -> {
            SettlementProductVO productVO = new SettlementProductVO();
            productVO.setPayWay(p.getPayType());
            productVO.setPayMonth(p.getMonth());
            productVO.setPayDate(NumberUtil.isNullOrZero(p.getMonthDay()) ?  (NumberUtil.isNullOrZero(p.getDays()) ? null : p.getDays()) : (NumberUtil.isNullOrZero(p.getMonthDay()) ? null : p.getMonthDay()));
            productVO.setProductNo(p.getProductNo());
            productVO.setName(p.getName());
            productVO.setSpec(p.getSpec());
            productVO.setCategory(p.getCategory());
            productVO.setBrand(p.getBrand());
            productVO.setUnit(p.getUnit());
            productVO.setTaxRate(p.getTaxRate().multiply(BigDecimal.valueOf(100)));
            productVO.setPrice(p.getRefPrice());
            productVO.setReceiveQuantity(p.getQuantity());
            return productVO;
        }).collect(Collectors.toList()));

        try {
            //转换为Json字符串，推送至消息队列
            String json = OrderStringUtil.serializeObject(orderVO);
            logger.info("发送订单结算信息 => " + json);
            rabbitTemplate.convertAndSend(SettleAccountsConstant.SA_AUTO_RECONCILIATION_EXCHANGE, SettleAccountsConstant.SA_AUTO_RECONCILIATION_ROUTINGKEY, json);
        } catch (Exception e) {
            logger.error("发送订单结算信息异常, msg:" + e.getMessage());
        }
    }

    /**
     * 订单支付后，将“平台”优惠券信息通知给结算服务
     *
     * @param vendorMemberId   供应会员Id
     * @param vendorRoleId     供应会员角色Id
     * @param vendorMemberName 供应会员名称
     * @param createTime       订单创建时间
     * @param submitTime       订单提交时间
     * @param orderType        订单类型枚举，定义在 OrderTypeEnum 中
     * @param orderNo          订单编号
     * @param digest           订单摘要
     * @param totalAmount      订单总金额
     * @param coupons          优惠券列表，key为优惠券Id，value为优惠券金额
     */
    @Async
    @Override
    public void notifyOrderCouponSettlement(Long vendorMemberId, Long vendorRoleId, String vendorMemberName, LocalDateTime createTime,  LocalDateTime submitTime, Integer orderType, String orderNo, String digest, BigDecimal totalAmount, Map<Long, BigDecimal> coupons) {
        if(coupons == null || coupons.isEmpty()) {
            return;
        }

        SettleAccountQueueDTO queueDTO = new SettleAccountQueueDTO();
        queueDTO.setType(SettleAccountQueueMessageTypeEnum.PLATFORM_COUPON_SETTLEMENT.getCode());
        queueDTO.setDelayTime(0);
        queueDTO.setTimes(0);

        PlatformCouponSettlementRequestVO requestVO = new PlatformCouponSettlementRequestVO();
        requestVO.setMemberId(vendorMemberId);
        requestVO.setRoleId(vendorRoleId);
        requestVO.setSettlementName(vendorMemberName);

        requestVO.setDetails(coupons.entrySet().stream().map(entry -> {
            PlatformCouponSettlementDetailRequestVO detailVO = new PlatformCouponSettlementDetailRequestVO();
            detailVO.setCouponId(entry.getKey());
            detailVO.setCouponAmount(entry.getValue().doubleValue());
            detailVO.setOrderNo(orderNo);
            detailVO.setOrderAbstract(digest);
            detailVO.setSettlementOrderType(SettlementOrderTypeEnum.ORDER.getCode());
            detailVO.setOrderTime(Objects.isNull(submitTime) ? OrderDateTimeUtil.localDateTimeToTimestamp(createTime) : OrderDateTimeUtil.localDateTimeToTimestamp(submitTime));
            detailVO.setOrderType(orderType);
            detailVO.setOrderAmount(totalAmount.doubleValue());
            return detailVO;
        }).collect(Collectors.toList()));

        String jsonMessage = OrderStringUtil.serializeObject(requestVO);
        queueDTO.setMessage(jsonMessage);

        //转换为Json字符串，推送至消息队列
        String queueMessage = OrderStringUtil.serializeObject(queueDTO);

        try {
            logger.info("发送平台优惠券结算信息 => " + queueMessage);
            rabbitTemplate.convertAndSend(SettleAccountsConstant.SETTLE_ACCOUNT_BASE_EXCHANGE, SettleAccountsConstant.SETTLE_ACCOUNT_BASE_ROUTING_KEY, queueMessage);
        } catch (Exception e) {
            logger.error("发送平台优惠券结算信息异常, msg:" + e.getMessage());
        }
    }
}
